unit MuUtils;

interface

uses SysUtils, Classes;

const
  kb = 1024;
  Mb = 1024 * kb;
  Gb = 1024 * Mb;

  OneDay = 1.0;
  OneHour = 1.0 / 24.0;
  OneMinute = OneHour / 60.0;
  OneSecond = OneMinute / 60.0;

type
  PByteArray = ^TByteArray;
  TByteArray = array[0..1*Gb] of Byte;

  TByteSet = set of Byte;
  TCharSet = set of Char;

const
  AllChars = [#1..#255];

  SpaceChars = [#1..#32];
  UpperCaseLetters = ['A'..'Z'];
  LowerCaseLetters = ['a'..'z'];
  Digits = ['0'..'9'];
  HexDigites = ['0'..'9', 'A'..'F', 'a'..'f'];

  Letters = LowerCaseLetters + UpperCaseLetters;
  IdSymbols = Letters + Digits + ['_'];


function Iif(Condition: Boolean; const TrueValue, FalseValue: Integer): Integer; overload;
function Iif(Condition: Boolean; const TrueValue, FalseValue: Extended): Extended; overload;
function Iif(Condition: Boolean; const TrueValue, FalseValue: string): string; overload;

function IsNil(const S, NullValue: string): string;
function Avail(const S: string; IndexFrom: Integer): string;
function LastChar(const S: string): Char;
function EasyCrypt(const S: string): string;
function EasyUncrypt(const S: string): string;

procedure ClearObjectList(L: TList);
procedure FreeObjectList(L: TList);
procedure ClearThreadObjectList(ThreadList: TThreadList);
procedure FreeThreadObjectList(ThreadList: TThreadList);

procedure WritePersistent(S: TStream; Instance: TPersistent);
procedure ReadPersistent(S: TStream; Instance: TPersistent);

implementation



{ General rounines }

function Iif(Condition: Boolean; const TrueValue, FalseValue: Integer): Integer; overload;
begin
  if Condition
    then Result := TrueValue
    else Result := FalseValue
end;

function Iif(Condition: Boolean; const TrueValue, FalseValue: Extended): Extended; overload;
begin
  if Condition
    then Result := TrueValue
    else Result := FalseValue
end;

function Iif(Condition: Boolean; const TrueValue, FalseValue: string): string; overload;
begin
  if Condition
    then Result := TrueValue
    else Result := FalseValue
end;





{ String routines }

function IsNil(const S, NullValue: string): string;
begin
  Result := Iif(S <> '', S, NullValue);
end;

function Avail(const S: string; IndexFrom: Integer): string;
begin
  Result := Copy(S, IndexFrom, Length(S) - IndexFrom + 1);
end;

function LastChar(const S: string): Char;
var
  Len: Integer;
begin
  Len := Length(S);
  if Len = 0
    then Result := #0
    else Result := S[Len]
end;

const
  CryptKey: array[0..3] of Byte = ($FA, $CE, $CA, $FE);

function GetKeyItem(I: Integer): Byte;
begin
  Result := CryptKey[I mod Length(CryptKey)];
end;

function EasyCrypt(const S: string): string;
var
  I, Len: Integer;
  Acc: Byte;
begin
  Len := Length(S);
  SetLength(Result, Len);

  Acc := 0;
  for I := 1 to Len do
  begin
    Byte(Result[I]) := Byte(S[I]) xor GetKeyItem(I) xor Acc;
    Acc := Byte(Result[I]) and $A5;
  end;
end;

function EasyUncrypt(const S: string): string;
var
  I, Len: Integer;
  Acc: Byte;
begin
  Len := Length(S);
  SetLength(Result, Len);

  Acc := 0;
  for I := 1 to Len do
  begin
    Byte(Result[I]) := Byte(S[I]) xor GetKeyItem(I) xor Acc;
    Acc := Byte(S[I]) and $A5;
  end;
end;





{ Classes routines }

procedure ClearObjectList(L: TList);
var
  I: Integer;
begin
  if L = nil then Exit;
  for I := L.Count - 1 downto 0 do
    TObject(L[I]).Free();
  L.Clear();
end;

procedure FreeObjectList(L: TList);
begin
  ClearObjectList(L);
  L.Free();
end;

procedure ClearThreadObjectList(ThreadList: TThreadList);
var
  L: TList;
begin
  L := ThreadList.LockList();
  try
    ClearObjectList(L);
  finally
    ThreadList.UnlockList();
  end;
end;

procedure FreeThreadObjectList(ThreadList: TThreadList);
begin
  ClearThreadObjectList(ThreadList);
  ThreadList.Free();
end;

type
  TMyWriter = class(TWriter)
  public
    procedure WritePersistent(Instance: TPersistent);
  end;

procedure TMyWriter.WritePersistent(Instance: TPersistent);
begin
  WriteProperties(Instance);
  WriteListEnd;
end;

type
  TMyReader = class(TReader)
  public
    procedure ReadPersistent(Instance: TPersistent);
  end;

procedure TMyReader.ReadPersistent(Instance: TPersistent);
begin
  while not EndOfList do
    ReadProperty(Instance);
  ReadListEnd;
end;

procedure WritePersistent(S: TStream; Instance: TPersistent);
var
  Writer: TMyWriter;
begin
  Writer := TMyWriter.Create(S, 4096);
  try
    Writer.WritePersistent(Instance);
  finally
    Writer.Free;
  end;
end;

procedure ReadPersistent(S: TStream; Instance: TPersistent);
var
  Reader: TMyReader;
begin
  Reader := TMyReader.Create(S, 4096);
  try
    Reader.ReadPersistent(Instance);
  finally
    Reader.Free;
  end;
end;


end.